/*
 * Copyright 2011 J. Auer, J. Andert, F.-J. Jendrusch, U. Celebi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package de.fuberlin.replication.application;

import de.fuberlin.replication.communication.Communication;
import de.fuberlin.replication.library.Metadata;
import de.fuberlin.replication.logging.Logger;
import de.fuberlin.replication.storage.Storage;

/**
 * Synchronizable application interface. Every application that wants to use the library needs to implement this
 * interface in order to allow interaction with the library.
 */
public interface Synchronizable {
	/**
	 * Returns the application- and device-specific logger implementation.
	 * 
	 * @return the application- and device-specific logger implementation.
	 */
	Logger getLogger();

	/**
	 * Returns the unique device address.
	 * 
	 * @return the unique device address.
	 */
	String getAddress();

	/**
	 * Returns the application- and device-specific storage implementation.
	 * 
	 * @return the application- and device-specific storage implementation.
	 */
	Storage getStorage();

	/**
	 * Returns the application- and device-specific communication implementation.
	 * 
	 * @return the application- and device-specific communication implementation.
	 */
	Communication getCommunication();

	/**
	 * Synchronization start callback.
	 */
	void onSynchronizationStart();

	/**
	 * Conflict solution algorithm. The returned metadata has to be one of the given. If the result should be modified,
	 * always modify and return the remote metadata. Changes on the local metadata won't be persisted!
	 * 
	 * @param local the local metadata.
	 * @param remote the remote metadata.
	 * @return the most recent metadata.
	 */
	Metadata onSynchronizationConflict(Metadata local, Metadata remote);

	/**
	 * Synchronization exception callback.
	 * 
	 * @param e the exception.
	 */
	void onSynchronizationException(Exception e);

	/**
	 * Synchronization stop callback.
	 */
	void onSynchronizationStop();

	/**
	 * Update start callback.
	 * 
	 * @param name the object name.
	 */
	void onUpdateStart(String name);

	/**
	 * Update exception callback.
	 * 
	 * @param name the object name.
	 * @param e the exception.
	 */
	void onUpdateException(String name, Exception e);

	/**
	 * Update stop callback.
	 * 
	 * @param name the object name.
	 */
	void onUpdateStop(String name);

	/**
	 * Returns the object matching the given name.
	 * 
	 * @param name the restricting name.
	 * @return the matching object.
	 */
	Object getObject(String name);

	/**
	 * Persistently stores the given object by the given name.
	 * 
	 * @param name the name.
	 * @param o the object.
	 */
	void putObject(String name, Object o);
}